﻿using System;
using System.Configuration;

namespace TypeBuilderFx.Core
{
    /// <summary>Component providing the default <see cref="ITypeEmitterCache"/> instance.</summary>
    /// <remarks>
    /// This component reads the configuration file in order to determine which implementation to use.
    /// If the app-setting key <c>TypeBuilderFx.Core.TypeEmitterCacheProvider.AssemblyName</c> is present, then
    /// the default cache will be one writing the dynamic components to disk.  Otherwise, it simply takes an in-memory
    /// cache.
    /// </remarks>
    public static class TypeEmitterCacheProvider
    {
        private static readonly ITypeEmitterCache _defaultInstance = CreateDefaultInstance();

        private static ITypeEmitterCache CreateDefaultInstance()
        {
            string configKey = typeof(TypeEmitterCacheProvider).FullName + ".AssemblyName";
            string assemblyName = ConfigurationManager.AppSettings[configKey];

            if (string.IsNullOrEmpty(assemblyName))
            {
                return new InMemoryTypeEmitterCache();
            }
            else
            {
                //  Hook on process unloading event, in order to write the assembly (if need be) to disk
                AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
            
                return new DiskTypeEmitterCache(assemblyName);
            }
        }

        /// <summary>Default type emitter cache.</summary>
        public static ITypeEmitterCache Default
        {
            get { return _defaultInstance; }
        }

        private static void CurrentDomain_DomainUnload(object sender, EventArgs e)
        {
            try
            {
                _defaultInstance.Dispose();
            }
            //  Make sure no exception leaks the domain unload event
            catch { }
        }
    }
}